package pers.cz.logtail.handler;

import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pers.cz.util.FileUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Map;

/**
 * @program: PostGirl-panent
 * @description: 测试监听文件变化
 * @author: Cheng Zhi
 * @create: 2022-10-04 11:57
 **/
public class LogListenner implements FileAlterationListener {

    Logger logger = LoggerFactory.getLogger(LogListenner.class);

    private Map<String, Long> fileLineRember;

    // RandomAccessFile randomAccessFile
    private Map<String, RandomAccessFile> fileRandowNote;

    public LogListenner(Map<String, Long> fileLineRember, Map<String, RandomAccessFile> fileRandowNote) {
        this.fileLineRember = fileLineRember;
        this.fileRandowNote = fileRandowNote;
    }

    @Override
    public void onStart(FileAlterationObserver fileAlterationObserver) {
        logger.debug("monitor start scan files..");
    }

    @Override
    public void onDirectoryCreate(File file) {
        String fileName = file.getName();
        logger.debug(fileName + " director created.");
    }

    @Override
    public void onDirectoryChange(File file) {

        String fileName = file.getName();
        logger.debug(fileName + " director created." );
    }

    @Override
    public void onDirectoryDelete(File file) {
        String fileName = file.getName();
        System.out.println();
        logger.debug(fileName + " director created.");
    }

    @Override
    public void onFileCreate(File file) {
        String fileName = file.getName();
        Long countLines = FileUtils.getFileLineCount(file);
        logger.debug(fileName + "  changed." + "count block size：" + countLines);
        fileLineRember.put(fileName, countLines);
    }

    @Override
    public void onFileChange(File file) {
        String fileName = file.getName();
        long oldLines = 0;

        // 注册文件句柄
        registeFileHandle(file);
        // 获取行数
        Long newLines = getFilePointer(file);
        // 注册文件修改
        if (fileLineRember.get(fileName) == null) {
            // 由于文件首次变更，程序不知道具体要处理哪行。
            logger.debug(fileName + "  file first change, not process!");
            fileLineRember.put(fileName, newLines);
            return;
        } else {
            oldLines = fileLineRember.get(fileName);
            logger.debug(fileName + "  old file size：" + oldLines);
        }
        logger.debug(fileName + "  changed." + "changed file size：" + newLines);
        fileLineRember.put(fileName, newLines);
        FileLineNote fileLineNote = new FileLineNote();
        fileLineNote.setStartLine(oldLines); // 起始指针
        fileLineNote.setEndLine(newLines); // 结尾指针
        fileLineNote.setFileName(fileName);
        fileLineNote.setFile(file);
        FileLineNodeQueue.push(fileLineNote);
    }

    @Override
    public void onFileDelete(File file) {

    }

    @Override
    public void onStop(FileAlterationObserver fileAlterationObserver) {

        logger.debug("monitor stop scanning..");
    }

    /**
     * 注册文件句柄
     * @param file
     */
    private void registeFileHandle(File file) {
        String fileName = file.getName();
        if (fileRandowNote.get(fileName) == null) {
            try {
                fileRandowNote.put(fileName, new RandomAccessFile(file,"r"));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取末尾指针位置，做为下次的初始指针
     * @param file
     * @return
     */
    private long getFilePointer(File file) {
        try {
            String fileName = file.getName();
            long length = file.length();
            long start = 0; //fileRandowNote.get(fileName).getFilePointer(); // 获取初始指针
            fileRandowNote.get(fileName).seek(start + length); // 将指针指向末尾
            return fileRandowNote.get(fileName).getFilePointer();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }
}
